package com.testing.sunnycommon.security.filter;

import com.testing.sunnycommon.model.SunnyUser;
import com.testing.sunnycommon.security.jwt.JwtUtils;
import com.testing.sunnycommon.service.SunnyUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @Classname SunnyJwtAuthenticationFilter
 * @Description 继承OncePerRequestFilter，在每个请求之前调用一次。用来完成各个接口调用之前的token的校验。
 * @Date 2023/6/30 22:41
 * @Created by 特斯汀Roy
 */
@Component
public class SunnyJwtAuthenticationFilter extends OncePerRequestFilter {

    @Autowired
    JwtUtils jwtUtils;

    @Autowired
    SunnyUserService sunnyUserService;


    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        //如果请求的是登录或者注册接口，那么不执行对token校验的逻辑
        if (request.getRequestURI().equals("/sunnyUser/login")
                || request.getRequestURI().equals("/sunnyUser/register")) {
            //直接去调用对应的接口
            filterChain.doFilter(request, response);
            return;
        }
        //拿token，然后从token中获取用户名，查询数据库中是否有这个用户
        //并且验证token是否还在有效期之内。
        String authHeader = request.getHeader(JwtUtils.HEADER_STRING);
        //如果token能够完成鉴权，那么为Security的context中加上鉴权信息，供之后security完成url权限的校验。
        if (authHeader != null) {
            //截取Bearer 之后的实际的token值。
            String tokenValue = authHeader.substring(JwtUtils.TOKEN_PREFIX.length());
            String usernameFromToken = jwtUtils.getUsernameFromToken(tokenValue);
            //判断当前security的context中，如果没有进行鉴权存储的话，把鉴权信息保存下来
            if (usernameFromToken != null && SecurityContextHolder.getContext().getAuthentication() == null) {
                SunnyUser existUser = sunnyUserService.loadUserByUsername(usernameFromToken);
                //验证token是否是有效的
                if (jwtUtils.validateToken(tokenValue, existUser)) {
                    //如果token是有效的，说明携带的token中的用户已经登录了
                    UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(existUser, null, existUser.getAuthorities());
                    //在鉴权信息中记录本次请求的信息作为详情
                    authenticationToken.setDetails(
                            new WebAuthenticationDetailsSource().buildDetails(request));
                    SecurityContextHolder.getContext().setAuthentication(authenticationToken);
                    System.out.println("携带token鉴权之后的结果是" + SecurityContextHolder.getContext().getAuthentication());
                }
            }
        }
        //应用过滤器执行
        filterChain.doFilter(request, response);

    }
}
